#ifndef SROS_SENSOR_IMU_HPP
#define SROS_SENSOR_IMU_HPP

#include <commons/impl/noncopyable.hpp>
#include <commons/hal/uart.hpp>
#include <commons/math/math.hpp>
#include <commons/type/ret.hpp>

#include <stdint.h>
#include <functional>

namespace sros::sensor
{
    class IMU : impl::noncopyable
    {
    public:
        struct Param
        {
            // 设备地址
            uint8_t addr = 0;

            /* Desc: 9轴数据回调接口
            ** 触发时机: 当9轴数据到达
            ** 参数:
            **  const uint64_t&&: 时间戳 ns
            **  const Vector9d<float>&&: 9轴数据v
            ** Default:如果没有设置，则有默认值，自动以sros_debug模式打印接收到的数据;*/
            std::function<void(const uint64_t &&, const Vector9d<float> &&)> on_asix_data_arrival;
        };
        
		/* Desc: 创建一个IMU设备操作类，构造参数只会初始化参数
        ** 参数: 
		**	hal::UartParam: 串口参数
        **  Param: imu参数
        */
        IMU(const hal::UartParam &uart_param, const Param &imu_param);
        
        ~IMU() = default;

        // Desc: 非阻塞模式, 线程安全.
        void run();

        // Desc: 非阻塞模式, 线程安全.
        void close();

        /* Desc: 设置传感器输出模式, 线程安全
        **  此功能可断电记忆
        ** 参数: mode
        **  00: 查询
        **  01: 5HZ 自动输出模式
        **  02: 15HZ 自动输出模式
        **  03: 25HZ 自动输出模式
        **  04: 35HZ 自动输出模式
        **  05: 50HZ 自动输出模式
        **  06: 100HZ 自动输出模式
        **  07: 200HZ 自动输出模式
        ** 返回参数: ret.v true: 请求成功 false: 请求失败
		** 		    ret.msg: 请求成功则返回空
        */
        RetBool set_output_mode(const uint8_t &mode);
        
        /* Desc: 设置波特率, 线程安全
        **  此功能可断电记忆
        ** 参数: bitrate
        **  02: 9600
        **  03: 19200
        **  04: 38400
        **  05: 115200
        **  06: 230400
        **  07: 256000
        ** 返回参数: ret.v true: 请求成功 false: 请求失败
		** 		    ret.msg: 请求成功则返回空
        */
        RetBool set_bitrate(const uint8_t &bitrate);

        /* Desc: 请求9轴数据，线程安全
        ** 返回参数: ret.v true: 请求成功 false: 请求失败
		** 		    ret.msg: 请求成功则返回空
        */
        RetBool req_data();

        /* Desc: 方位角清零指令, 线程安全
        ** 返回参数: ret.v true: 请求成功 false: 请求失败
		** 		    ret.msg: 请求成功则返回空
        */
        RetBool reset();

    private:
        void init_(const hal::UartParam &uart_param, const Param &imu_param);

    private:
        std::shared_ptr<hal::Uart> uart_;
        std::shared_ptr<Param>     param_;
    };
}

#endif